<?php
    if (!defined('ZT')) exit;
        
    class Dato {
        const NUMERO = 'zt_dato_numero';                    const ENTERO = 'zt_dato_entero';          
        const ENTERO_POSITIVO = 'zt_dato_entero_positivo';  const CUALQUIERA = 'zt_dato_cualquiera';
        const NATURAL = 'zt_dato_natural';                  const FECHA = 'zt_dato_fecha';
        const ARCHIVO = 'zt_dato_archivo';                  const EMAIL = 'zt_dato_email';
        const IMAGEN = 'zt_dato_imagen';                    const IMAGEN_MANIPULABLE = 'zt_dato_imagen_manip';
        const BIT = 'zt_dato_bit';                          const CADENA = 'zt_dato_cadena';
        const CADENA_ARCHIVO = 'zt_dato_cadena_archivo';    const HORARIO = 'zt_dato_horario';

        static function RANGO($filtro, $min, $max)
        {
            return new ZT_Rango($filtro, $min, $max);
        }
        
        static function ARREGLO($filtro)
        {
            return new ZT_Arreglo($filtro);
        }
        
        static function MAPA( )
        {
            return new ZT_Mapa(func_get_args( ));
        }
        
        static function filtra_valor($valor, $filtro, $defecto = null)
        {
            $valor = (is_string($filtro) ? $filtro($valor) : $filtro->llama($valor));
            
            if ($valor !== null) {
                return $valor;
            }
            
            return $defecto;
        }
        
        static function filtra_arreglo($fuente, $nombre, $filtro, $defecto = null)
        {
            if (array_key_exists($nombre, $fuente)) {
                return self::filtra_valor($fuente[$nombre], $filtro, $defecto);
            }
            
            return $defecto;
        }
    }
    
    class ZT_Rango {
        private $filtro;
        private $min;
        private $max;
        
        function __construct($filtro, $min, $max)
        {
            $this->filtro = $filtro;
            $this->min = $min;
            $this->max = $max;
        }
        
        function llama($valor)
        {
            $valor = Dato::filtra_valor($valor, $this->filtro);
            
            if ($valor !== null && $valor >= $this->min && $valor <= $this->max) {
                return $valor;
            }
        }
    }
    
    class ZT_Arreglo {
        private $filtro;
        
        function __construct($filtro)
        {
            $this->filtro = $filtro;
        }
        
        function llama($arreglo)
        {
            if (is_array($arreglo)) {
                $nuevo = array( );
                
                foreach ($arreglo as $valor) {
                    $valor = Dato::filtra_valor($valor, $this->filtro);
                    
                    if ($valor === null) {
                        return null;
                    }
                    
                    $nuevo[] = $valor;
                }
                
                return $nuevo;
            }
        }
    }
    
    class ZT_Mapa {
        private $datos;
        
        function __construct($datos)
        {
            $this->datos = $datos;
        }
        
        function llama($arreglo)
        {
            if (is_array($arreglo)) {
                $verificar = array( );

                foreach ($this->datos as $datos) {
                    $clave = $datos[0];

                    if (!isset($arreglo[$clave]) || !is_array($arreglo[$clave])) {
                        return null;
                    }
                    
                    $nuevo = array( );
                    $filtro = $datos[1];

                    foreach ($arreglo[$clave] as $valor) {
                        $valor = Dato::filtra_valor($valor, $filtro);
                        
                        if ($valor === null) {
                            if (!array_key_exists(2, $datos)) {
                                return null;
                            }

                            $valor = $datos[2];
                        }
                        
                        $nuevo[] = $valor;
                    }

                    $arreglo[$clave] = $nuevo;
                    $verificar[count($nuevo)] = null;
                }

                if (count($verificar) > 1) {
                    return null;
                }
                
                $nuevo = array( );
                
                foreach ($arreglo as $clave => $datos) {
                    foreach ($datos as $numero => $valor) {
                        $nuevo[$numero][$clave] = $valor;
                    }
                }
                
                return $nuevo;
            }
        }
    }
    
    function zt_dato_numero($dato)
    {
        if (is_numeric($dato)) {
            return (float)$dato;
        }
    }
    
    function zt_dato_entero($dato)
    {
        if (is_numeric($dato)) {
            return (int)$dato;
        }
    }
    
    function zt_dato_entero_positivo($dato)
    {
        if (is_numeric($dato)) {
            $dato = (int)$dato;
                        
            if ($dato >= 0) {
                return $dato;
            }
        }
    }

    function zt_dato_natural($dato)
    {
        if (is_numeric($dato)) {
            $dato = (int)$dato;
                        
            if ($dato > 0) {
                return $dato;
            }
        }
    }
    
    function zt_dato_bit($dato)
    {
        $dato = filter_var($dato, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
        
        if ($dato !== null) {
            return (int)$dato;
        }
    }
     
    function zt_dato_fecha($dato)
    {
        if ($dato) {
            $dato = date_create($dato);
            
            if ($dato !== null) {
                return new Fecha($dato);
            }
        }
    }
    
    function zt_dato_cadena($dato)
    {
        return (string)$dato;
    }
    
    function zt_dato_cadena_archivo($dato)
    {
        $dato = (string)$dato;

        if (preg_match('/^[\w\.-]+$/', $dato)) {
            return $dato;
        }
    }
    
    function zt_dato_horario($dato)
    {
        $dato = (string)$dato;

        if (preg_match('/^(0[7-9]|1[0-9]|2[0-3]):[0-5](0|5)-(0[7-9]|1[0-9]|2[0-3]):[0-5](0|5)$/', $dato)) {
            return explode('-', $dato);
        }
    }
        
    function zt_dato_cualquiera($dato)
    {
        return true;
    }
    
    function zt_dato_archivo($dato)
    {
        return Upload::vincula($dato);
    }
    
    function zt_dato_email($dato)
    {
        if (filter_var($dato, FILTER_VALIDATE_EMAIL)) {
            return trim($dato);
        }
    }
    
    function zt_dato_imagen($dato)
    {
        $dato = Upload::vincula($dato);
        
        if ($dato) {
            return Imagen::abre($dato);
        }
    }
    
    function zt_dato_imagen_manip($dato)
    {
        $dato = Upload::vincula($dato);
        
        if ($dato) {
            return Imagen::abre_manipulable($dato);
        }
    }
?>